#define YB_T_NO_MATH 1
//#define YB_T_NO_IOSTREAM 1
//#define YB_T_NO_TIMING 1
#define YTEST_B 4
#include <ytest/timing.hpp>
//#include "../../Temp/test.h"
#include <ysbuild.h>

#define TEST_GUI 1
#define TEST_IMAGE 0

#include <iostream>
#include <stdexcept>
#include YFM_Win32_YCLib_COM
#include <shlobj.h>
#include <shlwapi.h>
//#include <Windows.Foundation.h>
#include <vector>
#include <string>
#include <algorithm>
#include <ystdex/functional.hpp>
#include <ystdex/iterator.hpp>
#if TEST_IMAGE
#	include <YSLib/Adaptor/Image.h>
#endif
#include YFM_Helper_HostWindow
#include <windows.h>
#include "../HelperEx/Shells.h"
#include YFM_NPL_Configuration // for NPL::A1::NodeLoader;
#include YFM_Helper_GUIApplication // for FetchEnvironment;
#include YFM_Helper_Environment // for complete Environment;
#include <ystdex/path.hpp>
#include YFM_YSLib_UI_TreeView
#include "../HelperEx/Shells.h"

using namespace std;
using namespace placeholders;
using namespace ystdex;
using namespace ytest::timing;
using namespace NPL;
using namespace YSLib;
using namespace Drawing;
#if 0
using YSLib::Timers::HighResolutionClock;
#endif
typedef std::chrono::steady_clock HighResolutionClock;

using UI::Widget;
using UI::Button;
using Host::Window;
using Host::NativeWindowHandle;
using Host::HostRenderer;


#if TEST_GUI == 1
class TestWnd : public UI::Window
{
public:
	Button b1, b2;
	Host::Window* p_wnd = {};
	Widget w1;
#if TEST_IMAGE
	HBitmap pixmap{u8R"(T:\a.png)"};
#endif
	ValueNode Node;

	TestWnd(const Rect& r)
		: UI::Window(r),
		b1({5, 5, 80, 32}), b2({90, 5, 80, 32}),
		w1({40, 40, 640, 480})
	{
		using namespace UI;

#if TEST_IMAGE
		auto buf(ImageCodec::Convert(pixmap));
		auto p_img(ystdex::make_shared<Image>(buf.GetBufferPtr(),
			buf.GetWidth(), buf.GetHeight()));
printf("bmp size:%s\n", to_string(buf.GetSize()).c_str());
		SetSizeOf(w1, buf.GetSize());
printf("wgt size:%s\n", to_string(GetSizeOf(w1)).c_str());
#endif

		*this += b1,
		*this += b2,
		*this += w1,
		yunseq(
			Background = SolidBrush(ColorSpace::Red),
			b1.Text = "改变大小",
			b2.Text = "还原大小",
			FetchEvent<Click>(b1) += std::bind(&TestWnd::AdjustClient,
				this, Size(640, 480), std::placeholders::_1),
			FetchEvent<Click>(b2) += std::bind(&TestWnd::AdjustClient,
				this, Size(480, 320), std::placeholders::_1),
#if TEST_IMAGE
			FetchEvent<Paint>(w1) += ImageBrush(std::move(p_img)),
#endif
			w1.Background = SolidBrush(ColorSpace::Blue)
		);
	}

private:
	void
	AdjustClient(const Size& s, UI::CursorEventArgs&&)
	{
		// NOTE: Directly setting client size now would be restored on
		//	invalidation.
	//	if(p_wnd)
	//		p_wnd->ResizeClient(s);
		SetSizeOf(*this, s);
	}
};
#endif

namespace YSLib
{

namespace UI
{

namespace
{

}


}

using namespace UI;

}


int
main()
{
	using namespace YSLib;
	using namespace platform_ex;

#if TEST_GUI == 2
//	YSLib::InitializeInstalled();

	COM com;

	while(wcin)
	{
	wstring ws;
	getline(wcin, ws);

	try
	{

		auto p_dsk = GetDesktopFolder();
		auto& dsk(p_dsk.GetObject());
		auto path = ParseDisplayName(dsk, ws.c_str());
//		auto path = ParseDisplayName(dsk, reinterpret_cast<const wchar_t*>(
//			String(in, Text::CharSet::GBK).c_str()));

		cout << ToANSI(GetDisplayName(dsk, path)) << endl
			<< "====" << endl;

		ShellFolderPtr psfFirstFolder;
		{
		//	HDirectory h_dir(BindPath(GetDesktopFolder().GetObject(),
		//		LocateFolder(CSIDL_PROGRAM_FILES)));
		//	HDirectory h_dir(GetDesktopFolder().GetObject());
			HDirectory h_dir(BindPath(dsk, path));

			for(FileIterator i(&h_dir); i != FileIterator(); ++i)
#if 0
			for(auto i(ystdex::make_transform(FileIterator(&h_dir),
				[](const FileIterator& i){
					return i.get()->GetName();
				})); i != FileIterator(); ++i)
#endif
			{
				cout << string(*i) << '\n';

				const auto& h(i.get());

				if(!psfFirstFolder && h->IsDirectory())
					psfFirstFolder = BindPath(*h->GetNativeHandle(),
						h->GetPathPtr());
			}
		}
#if 0
		cout << "\n\n";
		if(psfFirstFolder)
		{
			HDirectory h_dir(std::move(psfFirstFolder));

#if 0
			vector<string> vec;
		//	vector<size_t> vec;

			copy(FileIterator(&h_dir), FileIterator(), back_inserter(vec));
			for(const auto& x : vec)
				cout << x << endl;
#endif
			for(FileIterator i(&h_dir); i != FileIterator(); ++i)
				cout << string(*i) << endl;
		}
#endif
	}
	catch(COMException&)
	{}

	}

	cin.get();
#endif

#if TEST_GUI == 1
	GUIApplication app;
//	UI::Windows::ControlAdaptor dsk(::GetDesktopWindow());

#if TEST_IMAGE
	ImageCodec codec;
#endif
#if 1
	TestWnd wgt(Rect(80, 80, 800, 600));
	const NPL::A1::NodeLoader loader(FetchEnvironment().Global);
	WidgetLoader wgt_ldr(decltype(WidgetLoader::Convert)(
		ystdex::trivial_swap, std::bind(&NPL::A1::NodeLoader::LoadNode<
		string_view>, &loader, std::placeholders::_1)));
	const char tu_test[]{u8R"NPL(node_a
($type "Panel")
($bounds "128 64 600 440")($z "233")
(node_c
	($type "Control")
	($bounds "4 4 108 36")
	($z "24")
)
(node_o
	($type "Panel")
	($bounds "24 24 108 36")
)
(node_w
	($type "Widget")
	($bounds "0 0 80 24")
)
(node_b
	($type "Button")
	($bounds "72 64 96 24")
)
(node_p
	($type "Panel")
	($bounds "64 96 144 96")
	(
		node_l
		($type "Label")
		($bounds "4 4 128 64")
	)
)
(node_tc
	($type "TabControl")
	($bounds "128 96 320 168")
	(pnlPage1
		($type "Panel")
		(btn_1
			($type "Button")
			($bounds "10 10 40 20")
		)
		(lbl_2
			($type "Label")
			($bounds "12 40 60 20")
		)
	)
	(pnlPage2
		($type "Panel")
	)
)
(node_tr
	($type "TreeView")
	($bounds "64 224 360 192")
)
)NPL"};
	auto& node(wgt.Node);

	RegisterControls(wgt_ldr);
	wgt_ldr.Default.Register<TreeList, TreeView>({"TreeList", "TreeView"});
	wgt_ldr.Bounds.Register<TreeList, TreeView>({"TreeList", "TreeView"});
	node = wgt_ldr.LoadUILayout(tu_test);
	YTraceDe(Notice, "Size of children nodes: %u\n", unsigned(node.size()));

	auto getz = [](CursorEventArgs&& e){
		auto& w(e.GetSender());

		if(auto x = dynamic_cast<Panel*>(FetchContainerPtr(w).get()))
		{
			auto& xr(*x);
			std::clog << &w << "Z:" << int(xr.QueryZ(w)) << std::endl;
		}
	};

	wgt += AccessWidget(node);
	AccessWidget<Panel>(node).Background = SolidBrush(ColorSpace::Green),
	AccessWidget<Control>(node, "node_c").Background
		= SolidBrush(ColorSpace::Aqua);
	FetchEvent<Click>(AccessWidget<Control>(node, "node_c")) += getz,
	FetchEvent<Click>(AccessWidget<Panel>(node, "node_o")) += getz;
	AccessWidget<Panel>(node, "node_o").Background
		= SolidBrush(Color(242, 192, 54));
	FetchEvent<Paint>(AccessWidget<Widget>(node, "node_w"))
		= SolidBrush(ColorSpace::Yellow);
	AccessWidget<Button>(node, "node_b").Text = u"卧了个大槽";
	FetchEvent<Click>(AccessWidget<Button>(node, "node_b"))
		+= [&](CursorEventArgs&&){
			auto& lbl(AccessWidget<Label>(node, "node_p", "node_l"));

			lbl.Background = SolidBrush(Color(std::rand(), std::rand(),
				std::rand()));
			lbl.AutoWrapLine = true;
			lbl.Text += u"日";
			Invalidate(lbl);
			cout << lbl.Text.size() << endl;
			if(lbl.Text.size() > 16)
				lbl.Text = u"艹";
	};

//	std::freopen("NUL", "w", stdout);
	try
	{
		using string = YSLib::string;
		auto& tc(AccessWidget<TabControl>(node, "node_tc"));
		auto& tb(tc.GetTabBarRef());
		auto& tab1 = *new Button(Size(40, 15));
		auto& tab2 = *new Control(Size(30, 24));
		auto& pg1 = AccessWidget<Panel>(node, "node_tc", "pnlPage1");
		auto& pg2 = AccessWidget<Panel>(node, "node_tc", "pnlPage2");
		auto& tv = AccessWidget<TreeView>(node, "node_tr");
		auto& tr = tv.GetTreeListRef();

		yunseq(
		AccessWidget<Button>(node, "node_tc", "pnlPage1", "btn_1").Text
			= u"Text1",
		AccessWidget<Label>(node, "node_tc", "pnlPage1", "lbl_2").Text
			= u"测试文本2",
		tab1.Text = u"按钮",
		tab2.Background = SolidBrush(Color(130, 44, 211)),
		pg1.Background = SolidBrush(ColorSpace::Yellow),
		pg2.Background = SolidBrush(Color(27, 219, 21))
		);
		tb += tab1;
		tb += tab2;
		tc.Attach(tab1);
		tc.Attach(tab2);
		tc.UpdateTabPages();
		tr.ExtractText = [](const ValueNode& nd)->String{
			try
			{
				return TreeList::DefaultExtractText(nd);
			}
			catch(ystdex::bad_any_cast&)
			{}
			return "<NONE>";
		};
		tr.TreeRoot = PackNodes("YFramework",
			MakeNode("3.DataDirectory", string("DATA_DIRECTORY")),
			MakeNode("1.FontFile", string("DEF_FONT_PATH")),
			PackNodes("2.FF",
				MakeNode("A", string("AA")),
				PackNodes("xxx",
					MakeNode("yyy", string("YYY"))
				),
				MakeNode("B"),
				MakeNode("C", string("cc"))
			),
			MakeNode("3.FontDirectory", string("DEF_FONT_DIRECTORY")),
			PackNodes("4.",
				MakeNode("xyy", string("XYY"))
			),
			MakeNode("5.", string("DEF_FONT_DIRECTORY")),
			MakeNode("6.ExtraDir", string("DEF_FNT_DIRECTORY")),
			PackNodes("GJ.",
				MakeNode("x1", string("XX")),
				MakeNode("x2", string("")),
				MakeNode("x3", string("XY"))
			)
		);
		tv.BindView(3);
	}
	catch(WidgetNotFound& e)
	{
		std::cerr << e.NodeName << std::endl;
		std::cerr << e.what() << std::endl;
		std::cerr << typeid(e).name() << std::endl;
	}
	catch(std::exception& e)
	{
		std::cerr << e.what() << std::endl;
		std::cerr << typeid(e).name() << std::endl;
	}
	Host::ShowTopLevel(wgt, WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, 0);
	wgt.p_wnd = &Host::WaitForHostWindow(wgt);
#else
	UI::Label wgt(Drawing::Size(120, 24));

	wgt.Text = "Hello world!";
	Host::ShowTopLevel(wgt, WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, 0);
#endif
	Execute(app);
#endif
}

